package com.github.tetrisgame.ui.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.github.tetrisgame.utils.UIUtils;

public class VerifyInputView extends View {
    private final Paint gridPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final StringBuilder inputTextSB = new StringBuilder();
    private final TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
    private final Paint cursorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final float textSize = UIUtils.sp2pxF(16);
    private final int space = UIUtils.dp2px(8);
    private final int radius = UIUtils.dp2px(10);
    private final float cursorWidth = UIUtils.dp2pxF(2);
    private final int gridCount = 6;
    private float cursorHeight = 0;
    private int mSize = UIUtils.dp2px(30);
    private boolean visible = true;
    private OnInputListener inputListener;


    public VerifyInputView(Context context) {
        super(context);
        init();
    }

    public VerifyInputView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public VerifyInputView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void init() {
        setFocusable(true);
        setFocusableInTouchMode(true);
        setClickable(true);

        textPaint.setTextSize(textSize);
        textPaint.setColor(Color.BLACK);

        cursorPaint.setStyle(Paint.Style.FILL);
        cursorPaint.setColor(Color.parseColor("#3ED689"));
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        cursorHeight = fontMetrics.bottom - fontMetrics.top;
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        outAttrs.inputType = EditorInfo.TYPE_CLASS_PHONE;
        outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
        return new BaseInputConnection(this, false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            requestFocus();
            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
        }
        return true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
            if (inputTextSB.length() < gridCount) {
                inputTextSB.append((char) event.getUnicodeChar());
                invalidate();
                if (inputTextSB.length() == gridCount) {
                    if (inputListener != null) {
                        inputListener.onInput(inputTextSB.toString());
                    }
                }
            }

        }
        if (keyCode == KeyEvent.KEYCODE_DEL) {
            if (inputTextSB.length() > 0) {
                inputTextSB.deleteCharAt(inputTextSB.length() - 1);
                invalidate();
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        startBlinkCursor();
    }

    public void startBlinkCursor() {
        post(() -> {
            visible = !visible;
            postInvalidate();
            postDelayed(this::startBlinkCursor, 500);
        });
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthModel = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        if (widthModel == MeasureSpec.EXACTLY) {
            mSize = (widthSize - (gridCount + 1) * space) / 6;
        }
        setMeasuredDimension(mSize * gridCount + (gridCount + 1) * space, mSize + 2 * space);
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        drawGrid(canvas);
        drawCursor(canvas);
        drawText(canvas);
    }

    public void drawGrid(Canvas canvas) {
        int cursorIndex = inputTextSB.length();
        gridPaint.setColor(Color.parseColor("#E5E5E5"));
        gridPaint.setStyle(Paint.Style.FILL);
        for (int i = 0; i < gridCount; i++) {
            if (i == cursorIndex) continue;
            canvas.drawRoundRect(
                    space + i * (space + mSize),
                    space,
                    space + i * (space + mSize) + mSize,
                    space + mSize,
                    radius, radius,
                    gridPaint
            );
        }

        gridPaint.setColor(Color.parseColor("#3ED689"));
        gridPaint.setStyle(Paint.Style.STROKE);
        gridPaint.setStrokeWidth(UIUtils.dp2px(1));
        canvas.drawRoundRect(
                space + cursorIndex * (space + mSize),
                space,
                space + cursorIndex * (space + mSize) + mSize,
                space + mSize,
                radius, radius,
                gridPaint
        );
    }

    public void drawCursor(Canvas canvas) {
        if (inputTextSB.length() < gridCount) {
            if (visible) {
                int cursorIndex = inputTextSB.length();
                float left = space + (mSize - cursorWidth) / 2 + cursorIndex * (mSize + space);
                float top = (getHeight() - cursorHeight) / 2;
                float right = left + cursorWidth;
                float bottom = top + cursorHeight;
                canvas.drawRect(
                        left, top, right, bottom, cursorPaint
                );
            }
        }
    }

    public void drawText(Canvas canvas) {
        for (int i = 0; i < inputTextSB.length(); i++) {
            String text = inputTextSB.charAt(i) + "";
            float textWidth = textPaint.measureText(text);
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            float offset = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
            float x = space + (mSize - textWidth) / 2 + i * (mSize + space);
            float y = getHeight() / 2f + offset;
            canvas.drawText(text, x, y, textPaint);
        }
    }

    public void clear() {
        inputTextSB.setLength(0);
        invalidate();
    }

    public void setOnInputListener(OnInputListener listener) {
        this.inputListener = listener;
    }

    public interface OnInputListener {
        void onInput(String text);
    }
}


